#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "proto.h"

static void *thr_job(void *s)
{
	char snd_addr[NAMESIZE];
	int snd_port;
	char filename[NAMESIZE];
	FILE *fp;
	struct file_st snd_data;
	struct sockaddr_in raddr;
	int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	int i, c;

	// 复制一份以防原来的字符数组被修改
	strncpy(snd_addr, (char *) ((char **) s)[0], NAMESIZE);
	snd_port = *((int **) s)[1];
	strncpy(filename, (char *) ((char **) s)[2], NAMESIZE);

	printf("Client: %s:%d\n", snd_addr, snd_port);
	printf("File name: %s\n", filename);

	if (fp = fopen(filename, "r")) {
		// 返回文件内容
		memset(snd_data.bytes, '\0', FILESIZE);
		for (i = 0; i < FILESIZE - 1; i++) {
			c = fgetc(fp);
			if (c == EOF) {
				break;
			}
			snd_data.bytes[i] = c;
		}
		fclose(fp);
	} else { // 文件不存在，返回错误信息
		strncpy(snd_data.bytes, "File doesn't exist!\n", FILESIZE);
	}

	// 新建udp socket来给客户端返回内容
	raddr.sin_family = AF_INET;
	inet_aton(snd_addr, &raddr.sin_addr);
	raddr.sin_port = htons(snd_port);

	// 发送文件内容
	sendto(udp_socket, &snd_data, strlen(snd_data.bytes) + 1, \
			0, (struct sockaddr *) &raddr, sizeof (raddr));

	close(udp_socket);

	return (void *) 0;
}

int main(void)
{
	struct sockaddr_in laddr, raddr;
	socklen_t raddr_len; // 接收消息的长度
	int ret;
	struct msg_st rcv_data;
	int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	pthread_t tid;

	char* rcv_addr;
	int rcv_port;

	void *targs[3]; // 暂存线程启动参数，客户端地址&文件路径

	if (-1 == udp_socket) {
		perror("Error creating udp socket");
		exit(1);
	}

	laddr.sin_family = AF_INET;
	inet_aton(RCVADDR, &laddr.sin_addr);

	laddr.sin_port = htons(PORT);
	if (-1 == bind(udp_socket, (struct sockaddr *) &laddr, sizeof (laddr))) {
		perror("Error binding socket");
		goto ERROR;
	}

	raddr_len = sizeof (struct sockaddr_in);

	while (1) {
		ret = recvfrom(udp_socket, &rcv_data, sizeof (rcv_data), 0, (struct sockaddr *) &raddr, &raddr_len);
		if (-1 == ret) {
			perror("Error receiving data");
			goto ERROR;
		}

		rcv_addr = inet_ntoa(raddr.sin_addr);
		rcv_port = ntohs(raddr.sin_port);

		targs[0] = (void *) rcv_addr;  // 发信息的客户端的ip地址
		targs[1] = (void *) &rcv_port; // 发信息的客户端的端口号，是个整型数，把指针传过去
		targs[2] = (void *) rcv_data.name; // 请求的文件名

		pthread_create(&tid, NULL, thr_job, (void *) targs);
	}

	close(udp_socket);
	return 0;

ERROR:
	close(udp_socket);
	exit(1);
}

